package com.itbaizhan.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itbaizhan.config.ZookeeperConfig;
import com.itbaizhan.domain.OrderItem;
import com.itbaizhan.domain.Product;
import com.itbaizhan.domain.TOrder;
import com.itbaizhan.lock.DistributeRedisLock;
import com.itbaizhan.mapper.OrderItemMapper;
import com.itbaizhan.mapper.ProductMapper;
import com.itbaizhan.service.TOrderService;
import com.itbaizhan.mapper.TOrderMapper;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

/**
 * @author 13487
 * @description 针对表【t_order】的数据库操作Service实现
 * @createDate 2024-04-25 13:55:09
 */
@Service
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder>
        implements TOrderService {

    @Autowired
    private TOrderMapper tOrderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    PlatformTransactionManager platformTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private DistributeRedisLock distributeRedisLock;
    @Autowired
    private CuratorFramework client;

    /**
     * 使用synchronized实现同步锁--- 单体应用
     *
     * @param productId
     * @param count
     * @return
     */
//    @Transactional 不能用注解事务，要手动提交
    @Override
    public synchronized String createOrder(Integer productId, Long count) {

        TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);

        // 先判断传入参数是否符合
        Product product = productMapper.selectById(productId);
        if (product == null || product.getCount() < count) {
            platformTransactionManager.rollback(transaction);
            throw new RuntimeException("商品不存在或者商品余额不足！");
        }
        // 修改库存
        product.setCount(product.getCount() - count);
        productMapper.updateById(product);

        // 创建订单
        TOrder tOrder = new TOrder();
        tOrder.setOrderStatus(1);
        tOrder.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
        tOrder.setReceiverMobile("18834388781");
        tOrder.setReceiverName("张三");
        tOrderMapper.insert(tOrder);

        // 创建订单商品
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(tOrder.getId());
        orderItem.setProduceId(productId);
        orderItem.setPurchaseNum(count.intValue());
        orderItem.setPurchasePrice(product.getPrice());
        orderItemMapper.insert(orderItem);
        // 提交事务
        platformTransactionManager.commit(transaction);
        return tOrder.getId();
    }

    @Override
    @Transactional
    public String createOrderPessimisticlock(Integer productId, Long count) {
        // 先判断传入参数是否符合
//        Product product = productMapper.selectById(productId);

        Product product = productMapper.findByProductId(productId);
        if (product == null || product.getCount() < count) {
            throw new RuntimeException("商品不存在或者商品余额不足！");
        }
        // 修改库存
        product.setCount(product.getCount() - count);
        productMapper.updateById(product);

        // 创建订单
        TOrder tOrder = new TOrder();
        tOrder.setOrderStatus(1);
        tOrder.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
        tOrder.setReceiverMobile("18834388781");
        tOrder.setReceiverName("张三");
        tOrderMapper.insert(tOrder);

        // 创建订单商品
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(tOrder.getId());
        orderItem.setProduceId(productId);
        orderItem.setPurchaseNum(count.intValue());
        orderItem.setPurchasePrice(product.getPrice());
        orderItemMapper.insert(orderItem);
        return tOrder.getId();
    }

    @Override
    @Transactional
    public String createOrderOptimisticlock(Integer productId, Long count) {
        int retryCount = 0;
        int updateCount = 0;
        // 先判断传入参数是否符合
        Product product = productMapper.selectById(productId);

//        Product product = productMapper.findByProductId(productId);
        if (product == null || product.getCount() < count) {
            throw new RuntimeException("商品不存在或者商品余额不足！");
        }
        // 修改库存
//        product.setCount(product.getCount() - count);
//        productMapper.updateById(product);

        while (retryCount < 3 && updateCount == 0) {
            updateCount = this.reduceStock(product.getId(), count);
            retryCount++;
        }
        if (updateCount == 0) {
            throw new RuntimeException("库存不足");
        }


        // 创建订单
        TOrder tOrder = new TOrder();
        tOrder.setOrderStatus(1);
        tOrder.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
        tOrder.setReceiverMobile("18834388781");
        tOrder.setReceiverName("张三");
        tOrderMapper.insert(tOrder);

        // 创建订单商品
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(tOrder.getId());
        orderItem.setProduceId(productId);
        orderItem.setPurchaseNum(count.intValue());
        orderItem.setPurchasePrice(product.getPrice());
        orderItemMapper.insert(orderItem);
        return tOrder.getId();
    }

    /**
     * 用实现分布式锁----redis
     *
     * @param productId
     * @param count
     * @return
     */
    @Override
    @Transactional
    public String createOrderRedislock(Integer productId, Long count) {
        // 获得锁
        String key = "lock:";
        Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(key + productId, Thread.currentThread().getId() + "", 30, TimeUnit.SECONDS);
        if (!result) {
            return "不允许重复下单!";
        }
        try {
            Product product = productMapper.findByProductId(productId);
            if (product == null || product.getCount() < count) {
                throw new RuntimeException("商品不存在或者商品余额不足！");
            }
            // 修改库存
            product.setCount(product.getCount() - count);
            productMapper.updateById(product);

            // 创建订单
            TOrder tOrder = new TOrder();
            tOrder.setOrderStatus(1);
            tOrder.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
            tOrder.setReceiverMobile("18834388781");
            tOrder.setReceiverName("张三");
            tOrderMapper.insert(tOrder);

            // 创建订单商品
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(tOrder.getId());
            orderItem.setProduceId(productId);
            orderItem.setPurchaseNum(count.intValue());
            orderItem.setPurchasePrice(product.getPrice());
            orderItemMapper.insert(orderItem);
            return tOrder.getId();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 防止误删除
            if ((Thread.currentThread().getId() + "").equals(stringRedisTemplate.opsForValue().get(key + productId))) {
                stringRedisTemplate.delete(key + productId);
            }
        }
        return "抢光了";
    }

    /**
     * 使用实现分布式锁----redisssion解决分布式锁
     * @param productId
     * @param count
     * @return
     */
    @Override
    @Transactional
    public String createOrderRedissionlock(Integer productId, Long count) throws InterruptedException {
        if (!distributeRedisLock.lock(String.valueOf(productId))){
            return "创建失败";
        }
        try {
            Product product = productMapper.findByProductId(productId);
            if (product == null || product.getCount() < count) {
                throw new RuntimeException("商品不存在或者商品余额不足！");
            }
            // 修改库存
            product.setCount(product.getCount() - count);
            productMapper.updateById(product);

            // 创建订单
            TOrder tOrder = new TOrder();
            tOrder.setOrderStatus(1);
            tOrder.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
            tOrder.setReceiverMobile("18834388781");
            tOrder.setReceiverName("张三");
            tOrderMapper.insert(tOrder);

            // 创建订单商品
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(tOrder.getId());
            orderItem.setProduceId(productId);
            orderItem.setPurchaseNum(count.intValue());
            orderItem.setPurchasePrice(product.getPrice());
            orderItemMapper.insert(orderItem);
            return tOrder.getId();
        }catch (Exception e){
            e.printStackTrace();
            return "创建失败";
        }finally {
            distributeRedisLock.unlock(String.valueOf(productId));
        }

    }

    /**
     * 使用实现分布式锁----zookeeper
     *
     * @param productId
     * @param count
     * @return
     */
    @Override
    @Transactional
    public String createOrderZklock(Integer productId, Long count) throws Exception {
        InterProcessMutex lock = new InterProcessMutex(client, "/lockPath");
        if (!lock.acquire(3,TimeUnit.SECONDS)){
            return "创建失败";
        }
        try{
            Product product = productMapper.findByProductId(productId);
            if (product == null || product.getCount() < count) {
                throw new RuntimeException("商品不存在或者商品余额不足！");
            }
            // 修改库存
            product.setCount(product.getCount() - count);
            productMapper.updateById(product);

            // 创建订单
            TOrder tOrder = new TOrder();
            tOrder.setOrderStatus(1);
            tOrder.setOrderAmount(product.getPrice().multiply(new BigDecimal(count)));
            tOrder.setReceiverMobile("18834388781");
            tOrder.setReceiverName("张三");
            tOrderMapper.insert(tOrder);

            // 创建订单商品
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(tOrder.getId());
            orderItem.setProduceId(productId);
            orderItem.setPurchaseNum(count.intValue());
            orderItem.setPurchasePrice(product.getPrice());
            orderItemMapper.insert(orderItem);
            return tOrder.getId();
        }catch (Exception e){
            e.printStackTrace();
            return "创建失败";
        }finally {
            lock.release();
        }
    }

    @Transactional
    public int reduceStock(Integer id, Long count) {
        int result = 0;
        Product product = productMapper.selectById(id);
        result = productMapper.updateByIdAndVersion(id, count, product.getVersion());
        return result;
    }
}




